package com.stable.actor.network;

import lombok.extern.slf4j.Slf4j;

/**
 * 协议消息 - 用于网络通信的消息封装
 */
@Slf4j
public class ProtocolMessage {
    private String messageId;
    private String senderPath;
    private String targetPath;
    private Object payload;
    private long timestamp;

    // 新增字段
    private boolean expectResponse = false;  // 是否期望响应
    private String messageType = "normal";   // 消息类型: normal, ask, response, ack
    private int timeoutMs = 30000;           // 超时时间（毫秒）
    private String correlationId;            // 关联ID（用于ask模式）

    // 默认构造函数
    public ProtocolMessage() {
        this.messageId = generateMessageId();
        this.timestamp = System.currentTimeMillis();
    }

    // 基础构造函数
    public ProtocolMessage(String senderPath, String targetPath, Object payload) {
        this();
        this.senderPath = senderPath;
        this.targetPath = targetPath;
        this.payload = payload;
    }

    /**
     * 生成消息ID
     */
    private String generateMessageId() {
        return "msg-" + System.currentTimeMillis() + "-" + Math.abs(hashCode());
    }

    // getters and setters
    public String getMessageId() { return messageId; }
    public void setMessageId(String messageId) { this.messageId = messageId; }

    public String getSenderPath() { return senderPath; }
    public void setSenderPath(String senderPath) { this.senderPath = senderPath; }

    public String getTargetPath() { return targetPath; }
    public void setTargetPath(String targetPath) { this.targetPath = targetPath; }

    public Object getPayload() { return payload; }
    public void setPayload(Object payload) { this.payload = payload; }

    public long getTimestamp() { return timestamp; }
    public void setTimestamp(long timestamp) { this.timestamp = timestamp; }

    // 新增字段的getters and setters
    public boolean isExpectResponse() { return expectResponse; }
    public void setExpectResponse(boolean expectResponse) { this.expectResponse = expectResponse; }

    public String getMessageType() { return messageType; }
    public void setMessageType(String messageType) { this.messageType = messageType; }

    public int getTimeoutMs() { return timeoutMs; }
    public void setTimeoutMs(int timeoutMs) { this.timeoutMs = timeoutMs; }

    public String getCorrelationId() { return correlationId; }
    public void setCorrelationId(String correlationId) { this.correlationId = correlationId; }

    /**
     * 设置为ask消息
     */
    public ProtocolMessage asAskMessage(String correlationId) {
        this.messageType = "ask";
        this.expectResponse = true;
        this.correlationId = correlationId;
        this.timeoutMs = 30000; // ask消息默认30秒超时
        return this;
    }

    /**
     * 设置为响应消息
     */
    public ProtocolMessage asResponseMessage(String originalMessageId) {
        this.messageType = "response";
        this.expectResponse = false;
        this.correlationId = originalMessageId;
        return this;
    }

    /**
     * 设置为确认消息
     */
    public ProtocolMessage asAckMessage() {
        this.messageType = "ack";
        this.expectResponse = false;
        return this;
    }

    /**
     * 设置期望响应
     */
    public ProtocolMessage withExpectResponse(boolean expectResponse) {
        this.expectResponse = expectResponse;
        return this;
    }

    /**
     * 设置超时时间
     */
    public ProtocolMessage withTimeout(int timeoutMs) {
        this.timeoutMs = timeoutMs;
        return this;
    }

    /**
     * 检查是否是ask消息
     */
    public boolean isAskMessage() {
        return "ask".equals(messageType);
    }

    /**
     * 检查是否是响应消息
     */
    public boolean isResponseMessage() {
        return "response".equals(messageType);
    }

    /**
     * 检查是否是确认消息
     */
    public boolean isAckMessage() {
        return "ack".equals(messageType);
    }

    /**
     * 检查消息是否已过期
     */
    public boolean isExpired() {
        long currentTime = System.currentTimeMillis();
        return (currentTime - timestamp) > timeoutMs;
    }

    /**
     * 获取剩余有效时间
     */
    public long getRemainingTime() {
        long elapsed = System.currentTimeMillis() - timestamp;
        return Math.max(0, timeoutMs - elapsed);
    }

    /**
     * 创建响应消息
     */
    public static ProtocolMessage createResponse(ProtocolMessage original, Object responsePayload) {
        ProtocolMessage response = new ProtocolMessage();
        response.setSenderPath(original.getTargetPath());
        response.setTargetPath(original.getSenderPath());
        response.setPayload(responsePayload);
        response.setMessageType("response");
        response.setCorrelationId(original.getMessageId());
        response.setExpectResponse(false);
        return response;
    }

    /**
     * 创建确认消息
     */
    public static ProtocolMessage createAck(ProtocolMessage original) {
        ProtocolMessage ack = new ProtocolMessage();
        ack.setSenderPath(original.getTargetPath());
        ack.setTargetPath(original.getSenderPath());
        ack.setPayload(new AckResponse("ACK", true, "Message received"));
        ack.setMessageType("ack");
        ack.setCorrelationId(original.getMessageId());
        ack.setExpectResponse(false);
        return ack;
    }

    /**
     * 创建错误响应
     */
    public static ProtocolMessage createErrorResponse(ProtocolMessage original, String error) {
        ProtocolMessage errorResponse = new ProtocolMessage();
        errorResponse.setSenderPath(original.getTargetPath());
        errorResponse.setTargetPath(original.getSenderPath());
        errorResponse.setPayload(new ErrorResponse("ERROR", false, error));
        errorResponse.setMessageType("response");
        errorResponse.setCorrelationId(original.getMessageId());
        errorResponse.setExpectResponse(false);
        return errorResponse;
    }

    @Override
    public String toString() {
        return String.format("ProtocolMessage[id=%s, type=%s, from=%s, to=%s, expectResponse=%s]",
                messageId, messageType, senderPath, targetPath, expectResponse);
    }

    /**
     * 确认响应
     */
    public static class AckResponse {
        private final String type;
        private final boolean success;
        private final String message;

        public AckResponse(String type, boolean success, String message) {
            this.type = type;
            this.success = success;
            this.message = message;
        }

        public String getType() { return type; }
        public boolean isSuccess() { return success; }
        public String getMessage() { return message; }
    }

    /**
     * 错误响应
     */
    public static class ErrorResponse {
        private final String type;
        private final boolean success;
        private final String error;

        public ErrorResponse(String type, boolean success, String error) {
            this.type = type;
            this.success = success;
            this.error = error;
        }

        public String getType() { return type; }
        public boolean isSuccess() { return success; }
        public String getError() { return error; }
    }
}
